package com.mavenq.fly.utils;

import org.springframework.util.StopWatch;

import javax.naming.Name;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ReflectionUtils {
    // 缓存反射元数据，提升性能
    private static final Map<Class<?>, Map<String, Field>> FIELD_CACHE = new ConcurrentHashMap<>();
    private static final Map<Class<?>, Map<String, Method>> METHOD_CACHE = new ConcurrentHashMap<>();

    // 获取类中所有字段（包括父类）
    public static Field getField(Class<?> clazz, String fieldName) {
        return FIELD_CACHE
                .computeIfAbsent(clazz, k -> new HashMap<>())
                .computeIfAbsent(fieldName, name -> {
                    Class<?> current = clazz;
                    while (current != Object.class) {
                        try {
                            Field field = current.getDeclaredField(name);
                            field.setAccessible(true);
                            return field;
                        } catch (NoSuchFieldException e) {
                            current = current.getSuperclass();
                        }
                    }
                    throw new RuntimeException("Field not found: " + fieldName);
                });
    }

    // 获取类中指定方法（支持方法签名）
    public static Method getMethod(Class<?> clazz, String methodName, Class<?>... paramTypes) {
        String key = methodName + Arrays.hashCode(paramTypes);
        return METHOD_CACHE
                .computeIfAbsent(clazz, k -> new HashMap<>())
                .computeIfAbsent(key, k -> {
                    try {
                        Method method = clazz.getDeclaredMethod(methodName, paramTypes);
                        method.setAccessible(true);
                        return method;
                    } catch (NoSuchMethodException e) {
                        throw new RuntimeException("Method not found: " + methodName, e);
                    }
                });
    }

    // 创建实例（支持构造函数参数）
    public static <T> T newInstance(Class<T> clazz, Object... args) {
        try {
            if (args.length == 0) {
                return clazz.getDeclaredConstructor().newInstance();
            }
            Class<?>[] paramTypes = Arrays.stream(args)
                    .map(Object::getClass)
                    .toArray(Class<?>[]::new);
            Constructor<T> constructor = clazz.getDeclaredConstructor(paramTypes);
            constructor.setAccessible(true);
            return constructor.newInstance(args);
        } catch (Exception e) {
            throw new RuntimeException("Failed to create instance", e);
        }
    }

    // 获取字段值（泛型支持）
    @SuppressWarnings("unchecked")
    public static <T> T getFieldValue(Object obj, String fieldName) {
        try {
            Field field = getField(obj.getClass(), fieldName);
            return (T) field.get(obj);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    // 设置字段值
    public static void setFieldValue(Object obj, String fieldName, Object value) {
        try {
            Field field = getField(obj.getClass(), fieldName);
            field.set(obj, value);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        StopWatch stopWatch = new StopWatch("工具类性能测试");
        stopWatch.start("第一次");
        ReflectionUtils.getField(WangCai.class, "name");
        stopWatch.stop();
        stopWatch.start("第二次");
        ReflectionUtils.getField(WangCai.class, "name");
        stopWatch.stop();
        stopWatch.start("第三次");
        ReflectionUtils.getField(WangCai.class, "name");
        stopWatch.stop();
        for (StopWatch.TaskInfo info : stopWatch.getTaskInfo()) {
            System.out.println(info.getTaskName() + "花费了" + info.getTimeMillis() + "ms");
        }
    }

    class Animal {
        private String name;
    }

    class Dog extends Animal {
        private String color;
    }

    class WangCai extends Dog {

    }
}